﻿using System;
using System.Drawing;
using System.Windows.Forms;
using AiFrame.Interface.WinUI.Windows.Controls;
using AiFrame.InterfaceLib.Data.Patterns;
using AiFrame.InterfaceLib.MVP;
using AiFrame.InterfaceLib.Windows.Themes;

namespace AiFrame.Interface.WinUI.Windows.UI
{
    public partial class AbstractListFrame : AbstractFrame, IAbstractFilterListView, IWindow, ICustomizableUIListView,
        IErrorDisplayable, IMessageDisplayable, ICustomizableMenuView
    {
        protected CustomizedListView _listView;
        
        public AbstractListFrame(): base()
        {
            InitializeComponent();
            
        }

        /// <summary>
        /// Initialisiert das Frame.
        /// </summary>
        /// <param name="styleGuideUI"></param>
        /// <param name="theme"></param>
        /// <param name="headerImage">Gibt ein Header-Image an. Wenn es null ist, wird ein Standard-
        /// <param name="resizeColumns">Gibt an, ob die Spaltenbreite automatisch angepasst werden soll.</param>
        /// Image benutzt.</param>
        protected void Initialize(IStyleGuideUI styleGuideUI, ITheme theme, Image headerImage, bool resizeColumns)
        {
            Dock = DockStyle.Fill;

            /* KundenlisteFrame anzeigen */
            _listView = new CustomizedListView(resizeColumns);
            _listView.Parent = dockPanel;
            _listView.Dock = DockStyle.Fill;

            base.InitializeAbstractFrame(styleGuideUI, theme, headerImage);
            _listView.ColumnClick += new ColumnClickEventHandler(_listView_ColumnClick);
        }

        /// <summary>
        /// Gibt an, welche Spalte sortiert werden soll.
        /// Das ist die Spalte, auf die zum letzten Mal
        /// geklickt worden ist.
        /// </summary>
        protected int SortColumn { get; set; }

        /// <summary>
        /// Gibt die Sortierrichtung an.
        /// </summary>
        protected SortDirection SortOrder { get; set; }

        void _listView_ColumnClick(object sender, ColumnClickEventArgs e)
        {
            /* Wenn die alte Sortierspalte gleich der neuen ist,
             * dann die Sortierreihenfolge umdrehen */
            if (SortColumn == e.Column)
            {
                if (this.SortOrder == SortDirection.Ascending)
                    this.SortOrder = SortDirection.Descending;
                else
                    this.SortOrder = SortDirection.Ascending;
            }
            else
            {
                /* Alte Sortierspalte ist ungleich der neuen */
                this.SortOrder = SortDirection.Ascending;
            }
            SortColumn = e.Column;
            
            /* Wird von der ableitenden Klasse behandelt */
            if (_listView.Columns[SortColumn].Tag != null && _listView.Columns[SortColumn].Tag is SortExpressionWrapper)
            {
                SortExpressionWrapper sortExpression = (SortExpressionWrapper)_listView.Columns[SortColumn].Tag;
                ColumnClick(sortExpression.PropertyPath);
            }
        }

        /// <summary>
        /// Gibt die ausgewählten Zeilen als Index-Array
        /// zurück.
        /// </summary>
        /// <returns></returns>
        protected int[] GetSelectedIndizes()
        {
            int[] indexes = new int[0];
            if (_listView.SelectedItems.Count > 0)
            {
                /* Alle ausgewählten Indizes in einem Array zusammenfassen */
                indexes = new int[_listView.SelectedItems.Count];
                for (int i = 0; i < _listView.SelectedItems.Count; i++)
                {
                    indexes[i] = _listView.SelectedItems[i].Index;
                }
            }
            return indexes;
        }

        protected virtual void ColumnClick(string propertyPath)
        {
            /* Dies wird von der erbenden Klasse implementiert.
             * Die ableitende Klasse muss den Presenter aufrufen,
             * um die Sortierparameter zu übergeben. */
        }


        public virtual void ShowToolBar() { }

        #region Implementation of IAbstractListView

        public void BeginUpdate()
        {
            _listView.BeginUpdate();
        }

        public void EndUpdate()
        {
            _listView.EndUpdate();
        }

        public void ClearItems()
        {
            _listView.Items.Clear();
        }

        public bool IsFiltered
        {
            get { return filterBar.State == FilterBar.FilterState.On; }
            set
            {
                if (value)
                    filterBar.State = FilterBar.FilterState.On;
                else
                    filterBar.State = FilterBar.FilterState.Off;
            }
        }

        public string FilterText
        {
            get { return searchTextBox.Text; }
            set { searchTextBox.Text = value; }
        }

        #endregion

        #region Implementation of ICustomizableUIListView

        public bool TopPanelVisible
        {
            get { return _topPanel.Visible; }
            set { _topPanel.Visible = value; }
        }

        public bool SearchPanelVisible
        {
            get { return filterPanel.Visible; }
            set { filterPanel.Visible = value; }
        }

        #endregion

        public event EventHandler ItemDoubleClickEvent
        {
            add
            {
                _listView.DoubleClick += value;
            }
            remove
            {
                _listView.DoubleClick -= value;
            }
        }

        public override void BringWindowToFront()
        {
            BringToFront();
            ShowToolBar();
        }

        #region Implementation of IErrorDisplayable

        public void DisplayError(string message)
        {
            MessageBox.Show(message, "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        #endregion

        private void searchTextBox_KeyPress(object sender, KeyPressEventArgs e)
        {
            /* Bei Enter-Eingabe den Muasklick auf den Suchen-Button
             * auslösen */
            if (e.KeyChar == '\r')
                searchButton.PerformClick();
        }

        #region Implementation of IMessageDisplayable

        public AnswerButton ShowYesNoQuestion(string caption, string message)
        {
            if (MessageBox.Show(message, caption, MessageBoxButtons.YesNo, MessageBoxIcon.Question,
                            MessageBoxDefaultButton.Button1) == DialogResult.Yes)
                return AnswerButton.Yes;
            
            return AnswerButton.No;
        }

        #endregion

        #region Implementation of IExportableList

        public string[,] GetExportedList()
        {
            string[,] exportList = new string[_listView.Items.Count + 1, _listView.Columns.Count];

            /* Die Überschriften übertragen */
            for (int i = 0; i < _listView.Columns.Count; i++)
            {
                exportList[0, i] = _listView.Columns[i].Text;
            }

            for (int i = 0; i < _listView.Items.Count; i++)
            {
                for (int y = 0; y < _listView.Columns.Count; y++)
                {
                    string text = "";

                    if (y == 0)
                        text = _listView.Items[i].Text;
                    else
                        text = _listView.Items[i].SubItems[y].Text;

                    /* Das 0te Element wird bereits von der Spaltenbezeichnung
                     * belegt, deswegen weiterrücken */
                    exportList[i + 1, y] = text;
                }
            }

            return exportList;
        }

        #endregion

        #region Implementation of ICustomizableMenuView

        public void SetContextMenu(object menu)
        {
            try
            {
                _listView.ContextMenuStrip = (ContextMenuStrip) menu;
            }
            catch (Exception e)
            {
                DisplayError("Das übergebene Menu ist kein gültiges ContextMenu.");
            }
        }

        #endregion
    }
}